﻿using System.Collections.Generic;
using System.Linq;
using Abp.Authorization;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace AbpDemo.WebApi
{
    public class SecurityRequirementsOperationFilter : IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            var actionAttrs = context.ApiDescription.ActionAttributes();
            var attrs = actionAttrs as object[] ?? actionAttrs.ToArray();
            if (attrs.OfType<AbpAllowAnonymousAttribute>().Any())
            {
                return;
            }

            var controllerAttrs = context.ApiDescription.ControllerAttributes();
            var actionAbpAuthorizeAttrs = attrs.OfType<AbpAuthorizeAttribute>();

            var abpAuthorizeAttributes = actionAbpAuthorizeAttrs as AbpAuthorizeAttribute[] ?? actionAbpAuthorizeAttrs.ToArray();
            var ctrlAttrs = controllerAttrs as object[] ?? controllerAttrs.ToArray();
            if (!abpAuthorizeAttributes.Any() && ctrlAttrs.OfType<AbpAllowAnonymousAttribute>().Any())
            {
                return;
            }

            var controllerAbpAuthorizeAttrs = ctrlAttrs.OfType<AbpAuthorizeAttribute>();
            var abpAuthorizeAttrs = controllerAbpAuthorizeAttrs as AbpAuthorizeAttribute[] ?? controllerAbpAuthorizeAttrs.ToArray();
            if (abpAuthorizeAttrs.Any() || abpAuthorizeAttributes.Any())
            {
                operation.Responses.Add("401", new Response { Description = "Unauthorized" });

                var permissions = abpAuthorizeAttrs.Union(abpAuthorizeAttributes)
                    .SelectMany(p => p.Permissions)
                    .Distinct();

                var permisArray = permissions as string[] ?? permissions.ToArray();
                if (permisArray.Any())
                {
                    operation.Responses.Add("403", new Response { Description = "Forbidden" });
                }

                operation.Security = new List<IDictionary<string, IEnumerable<string>>>
                {
                    new Dictionary<string, IEnumerable<string>>
                    {
                        { "bearerAuth", permisArray }
                    }
                };
            }
        }
    }
}
